home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 June / Chip_2002-06_cd1.bin / zkuste / delphi / kolekce / d6 / rxlibsetup.exe / {app} / units / DBQBE.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-02-19  |  17.3 KB  |  685 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 2001,2002 SGB Software          }
  6. {         Copyright (c) 1997, 1998 Fedor Koshevnikov,   }
  7. {                        Igor Pavluk and Serge Korolev  }
  8. {                                                       }
  9. {  Additional credits and thanks goto AO ROSNO and      }
  10. {  Master-Bank for there additions to this unit         }
  11. {*******************************************************}
  12.  
  13. unit DBQBE;
  14.  
  15. {$I RX.INC}
  16. {$N+,P+,S-}
  17.  
  18. interface
  19.  
  20. uses SysUtils, {$IFDEF WIN32} Windows, Bde, {$ELSE} WinTypes, WinProcs,
  21.   DbiErrs, DbiTypes, DbiProcs, {$ENDIF} Classes, Controls, DB, DBTables;
  22.  
  23. const
  24.   DefQBEStartParam = '#';
  25.  
  26. type
  27.   TCheckType = (ctNone, ctCheck, ctCheckPlus, ctCheckDesc, ctCheckGroup);
  28.  
  29. { TQBEQuery }
  30.  
  31.   TQBEQuery = class(TDBDataSet)
  32.   private
  33.     FStmtHandle: HDBIStmt;
  34.     FQBE: TStrings;
  35.     FPrepared: Boolean;
  36.     FParams: TParams;
  37.     FStartParam: Char;
  38.     FAuxiliaryTables: Boolean;
  39. {$IFDEF WIN32}
  40.     FText: string;
  41.     FRowsAffected: Integer;
  42. {$ELSE}
  43.     FText: PChar;
  44. {$ENDIF}
  45. {$IFDEF RX_D3}
  46.     FConstrained: Boolean;
  47. {$ENDIF}
  48.     FLocal: Boolean;
  49.     FRequestLive: Boolean;
  50.     FBlankAsZero: Boolean;
  51.     FParamCheck: Boolean;
  52.     function CreateCursor(GenHandle: Boolean): HDBICur;
  53.     procedure ReplaceParams(QBEText: TStrings);
  54.     procedure CreateParams(List: TParams; const Value: PChar);
  55.     procedure FreeStatement;
  56.     function GetQueryCursor(GenHandle: Boolean): HDBICur;
  57.     procedure GetStatementHandle(QBEText: PChar);
  58.     procedure PrepareQBE(Value: PChar);
  59.     procedure QueryChanged(Sender: TObject);
  60.     procedure SetQuery(Value: TStrings);
  61.     procedure SetParamsList(Value: TParams);
  62.     procedure SetPrepared(Value: Boolean);
  63.     procedure SetPrepare(Value: Boolean);
  64.     procedure SetStartParam(Value: Char);
  65. {$IFDEF RX_D4}
  66.     procedure ReadParamData(Reader: TReader);
  67.     procedure WriteParamData(Writer: TWriter);
  68. {$ENDIF}
  69. {$IFDEF WIN32}
  70.     function GetRowsAffected: Integer;
  71. {$ENDIF}
  72. {$IFDEF RX_D5}
  73.   protected
  74.     { IProviderSupport }
  75.     procedure PSExecute; override;
  76.     function PSGetParams: TParams; override;
  77.     procedure PSSetCommandText(const CommandText: string); override;
  78.     procedure PSSetParams(AParams: TParams); override;
  79. {$ENDIF}
  80.   protected
  81.     function CreateHandle: HDBICur; override;
  82.     procedure Disconnect; override;
  83.     function GetParamsCount: Word;
  84. {$IFDEF RX_D4}
  85.     procedure DefineProperties(Filer: TFiler); override;
  86. {$ENDIF}
  87. {$IFDEF RX_V110}
  88.     function SetDBFlag(Flag: Integer; Value: Boolean): Boolean; override;
  89. {$ELSE}
  90.     procedure SetDBFlag(Flag: Integer; Value: Boolean); override;
  91. {$ENDIF}
  92.   public
  93.     constructor Create(AOwner: TComponent); override;
  94.     destructor Destroy; override;
  95.     function GetQBEText: PChar;
  96.     procedure ExecQBE;
  97.     function ParamByName(const Value: string): TParam;
  98.     procedure Prepare;
  99.     procedure RefreshQuery;
  100.     procedure UnPrepare;
  101. {$IFNDEF RX_D3}
  102.     function IsEmpty: Boolean;
  103. {$ENDIF}
  104.     property Local: Boolean read FLocal;
  105.     property ParamCount: Word read GetParamsCount;
  106.     property Prepared: Boolean read FPrepared write SetPrepare;
  107.     property StmtHandle: HDBIStmt read FStmtHandle;
  108. {$IFDEF WIN32}
  109.     property Text: string read FText;
  110.     property RowsAffected: Integer read GetRowsAffected;
  111. {$ELSE}
  112.     property Text: PChar read FText;
  113. {$ENDIF}
  114.   published
  115. {$IFDEF RX_D5}
  116.     property AutoRefresh;
  117. {$ENDIF}
  118.     property AuxiliaryTables: Boolean read FAuxiliaryTables write FAuxiliaryTables default True;
  119.     property ParamCheck: Boolean read FParamCheck write FParamCheck default True;
  120.     property StartParam: Char read FStartParam write SetStartParam default DefQBEStartParam;
  121.     { Ensure StartParam is declared before QBE }
  122.     property QBE: TStrings read FQBE write SetQuery;
  123.     { Ensure QBE is declared before Params }
  124.     property BlankAsZero: Boolean read FBlankAsZero write FBlankAsZero default False;
  125.     property Params: TParams read FParams write SetParamsList {$IFDEF RX_D4} stored False {$ENDIF};
  126.     property RequestLive: Boolean read FRequestLive write FRequestLive default False;
  127.     property UpdateMode;
  128. {$IFDEF WIN32}
  129.     property UpdateObject;
  130.   {$IFDEF RX_D3}
  131.     property Constrained: Boolean read FConstrained write FConstrained default False;
  132.     property Constraints stored ConstraintsStored;
  133.   {$ENDIF}
  134. {$ENDIF}
  135.   end;
  136.  
  137. implementation
  138.  
  139. uses DBConsts, {$IFDEF RX_D3} BDEConst, {$ENDIF} DBUtils, BdeUtils;
  140.  
  141. function NameDelimiter(C: Char): Boolean;
  142. begin
  143.   Result := C in [' ', ',', ';', ')', '.', #13, #10];
  144. end;
  145.  
  146. function IsLiteral(C: Char): Boolean;
  147. begin
  148.   Result := C in ['''', '"'];
  149. end;
  150.  
  151. { TQBEQuery }
  152.  
  153. constructor TQBEQuery.Create(AOwner: TComponent);
  154. begin
  155.   inherited Create(AOwner);
  156.   FQBE := TStringList.Create;
  157.   TStringList(QBE).OnChange := QueryChanged;
  158.   FParams := TParams.Create{$IFDEF RX_D4}(Self){$ENDIF};
  159.   FStartParam := DefQBEStartParam;
  160.   FParamCheck := True;
  161.   FAuxiliaryTables:= True;
  162. {$IFNDEF WIN32}
  163.   FText := nil;
  164. {$ELSE}
  165.   FRowsAffected := -1;
  166. {$ENDIF}
  167.   FRequestLive := False;
  168. end;
  169.  
  170. destructor TQBEQuery.Destroy;
  171. begin
  172.   Destroying;
  173.   Disconnect;
  174.   QBE.Free;
  175. {$IFNDEF WIN32}
  176.   StrDispose(FText);
  177. {$ENDIF}
  178.   FParams.Free;
  179.   inherited Destroy;
  180. end;
  181.  
  182. procedure TQBEQuery.Disconnect;
  183. begin
  184.   Close;
  185.   UnPrepare;
  186. end;
  187.  
  188. procedure TQBEQuery.RefreshQuery;
  189. var
  190.   Bookmark: TBookmark;
  191. begin
  192.   DisableControls;
  193.   Bookmark := GetBookmark;
  194.   try
  195.     Close;
  196.     Open;
  197.     try
  198.       GotoBookmark(Bookmark);
  199.     except
  200.       { ignore exceptions }
  201.     end;
  202.   finally
  203.     FreeBookmark(Bookmark);
  204.     EnableControls;
  205.   end;
  206. end;
  207.  
  208. procedure TQBEQuery.SetPrepare(Value: Boolean);
  209. begin
  210.   if Value then Prepare
  211.   else UnPrepare;
  212. end;
  213.  
  214. procedure TQBEQuery.Prepare;
  215. begin
  216.   SetDBFlag(dbfPrepared, True);
  217.   SetPrepared(True);
  218. end;
  219.  
  220. procedure TQBEQuery.UnPrepare;
  221. begin
  222.   SetPrepared(False);
  223.   SetDBFlag(dbfPrepared, False);
  224. end;
  225.  
  226. procedure TQBEQuery.SetStartParam(Value: Char);
  227. begin
  228.   if Value <> FStartParam then begin
  229.     FStartParam := Value;
  230.     QueryChanged(nil);
  231.   end;
  232. end;
  233.  
  234. procedure TQBEQuery.SetQuery(Value: TStrings);
  235. begin
  236. {$IFDEF WIN32}
  237.   if QBE.Text <> Value.Text then begin
  238. {$ENDIF}
  239.     Disconnect;
  240.     TStringList(QBE).OnChange := nil;
  241.     QBE.Assign(Value);
  242.     TStringList(QBE).OnChange := QueryChanged;
  243.     QueryChanged(nil);
  244. {$IFDEF WIN32}
  245.   end;
  246. {$ENDIF}
  247. end;
  248.  
  249. procedure TQBEQuery.QueryChanged(Sender: TObject);
  250. var
  251.   List: TParams;
  252. begin
  253. {$IFDEF RX_D4}
  254.   if not (csReading in ComponentState) then begin
  255. {$ENDIF RX_D4}
  256.     Disconnect;
  257.   {$IFDEF WIN32}
  258.     FText := QBE.Text;
  259.   {$ELSE}
  260.     StrDispose(FText);
  261.     FText := QBE.GetText;
  262.   {$ENDIF WIN32}
  263.     if ParamCheck or (csDesigning in ComponentState) then begin
  264.       List := TParams.Create{$IFDEF RX_D4}(Self){$ENDIF};
  265.       try
  266.         CreateParams(List, PChar(Text));
  267.         List.AssignValues(FParams);
  268.     {$IFDEF RX_D4}
  269.         FParams.Clear;
  270.         FParams.Assign(List);
  271.       finally
  272.     {$ELSE}
  273.         FParams.Free;
  274.         FParams := List;
  275.       except
  276.     {$ENDIF RX_D4}
  277.         List.Free;
  278.       end;
  279.     end;
  280. {$IFDEF RX_D4}
  281.     DataEvent(dePropertyChange, 0);
  282.   end
  283.   else begin
  284.     FText := QBE.Text;
  285.     FParams.Clear;
  286.     CreateParams(FParams, PChar(Text));
  287.   end;
  288. {$ENDIF RX_D4}
  289. end;
  290.  
  291. procedure TQBEQuery.SetParamsList(Value: TParams);
  292. begin
  293.   FParams.AssignValues(Value);
  294. end;
  295.  
  296. {$IFDEF RX_D4}
  297. procedure TQBEQuery.DefineProperties(Filer: TFiler);
  298. begin
  299.   inherited DefineProperties(Filer);
  300.   Filer.DefineProperty('ParamData', ReadParamData, WriteParamData, True);
  301. end;
  302.  
  303. procedure TQBEQuery.ReadParamData(Reader: TReader);
  304. begin
  305.   Reader.ReadValue;
  306.   Reader.ReadCollection(FParams);
  307. end;
  308.  
  309. procedure TQBEQuery.WriteParamData(Writer: TWriter);
  310. begin
  311.   Writer.WriteCollection(Params);
  312. end;
  313. {$ENDIF}
  314.  
  315. function TQBEQuery.GetParamsCount: Word;
  316. begin
  317.   Result := FParams.Count;
  318. end;
  319.  
  320. procedure TQBEQuery.ReplaceParams(QBEText: TStrings);
  321.  
  322.   function ReplaceString(const S: string): string;
  323.   var
  324.     I, J, P, LiteralChars: Integer;
  325.     Param: TParam;
  326.     Temp: string;
  327.     Found: Boolean;
  328.   begin
  329.     Result := S;
  330.     for I := Params.Count - 1 downto 0 do begin
  331.       Param := Params[I];
  332.       if Param.DataType = ftUnknown then
  333.         Continue; { ignore undefined params }
  334.       repeat
  335.         P := Pos(StartParam + Param.Name, Result);
  336.         Found := (P > 0) and ((Length(Result) = P + Length(Param.Name)) or
  337.           NameDelimiter(Result[P + Length(Param.Name) + 1]));
  338.         if Found then begin
  339.           LiteralChars := 0;
  340.           for J := 1 to P - 1 do
  341.             if IsLiteral(Result[J]) then Inc(LiteralChars);
  342.           Found := LiteralChars mod 2 = 0;
  343.           if Found then begin
  344.             Temp := Param.Text;
  345.             if Temp = '' then begin
  346.               if (Param.DataType = ftString) and not Param.IsNull then
  347.                 Temp := '""'
  348.               else Temp := 'BLANK'; { special QBE operator }
  349.             end;
  350.             Result := Copy(Result, 1, P - 1) + Temp + Copy(Result,
  351.               P + Length(Param.Name) + 1, MaxInt);
  352.           end;
  353.         end;
  354.       until not Found;
  355.     end;
  356.   end;
  357.  
  358. var
  359.   I: Integer;
  360. begin
  361.   for I := 0 to QBEText.Count - 1 do
  362.     QBEText[I] := ReplaceString(QBEText[I]);
  363. end;
  364.  
  365. procedure TQBEQuery.SetPrepared(Value: Boolean);
  366. var
  367.   TempQBE: TStrings;
  368.   AText: PChar;
  369. begin
  370.   if Handle <> nil then _DBError(SDataSetOpen);
  371.   if (Value <> Prepared) or (ParamCount > 0) then begin
  372.     if Value then begin
  373. {$IFDEF WIN32}
  374.       FRowsAffected := -1;
  375. {$ENDIF}
  376.       if ParamCount > 0 then begin
  377.         TempQBE := TStringList.Create;
  378.         try
  379.           TempQBE.Assign(QBE);
  380.           ReplaceParams(TempQBE);
  381. {$IFDEF WIN32}
  382.           AText := PChar(TempQBE.Text);
  383. {$ELSE}
  384.           AText := TempQBE.GetText;
  385. {$ENDIF}
  386.           try
  387.             FreeStatement;
  388.             if StrLen(AText) > 1 then PrepareQBE(AText)
  389.             else _DBError(SEmptySQLStatement);
  390.           finally
  391. {$IFNDEF WIN32}
  392.             StrDispose(AText);
  393. {$ENDIF}
  394.           end;
  395.         finally
  396.           TempQBE.Free;
  397.         end;
  398.       end
  399.       else begin
  400.         if StrLen(PChar(Text)) > 1 then PrepareQBE(PChar(Text))
  401.         else _DBError(SEmptySQLStatement);
  402.       end;
  403.     end
  404.     else begin
  405. {$IFDEF WIN32}
  406.       FRowsAffected := RowsAffected;
  407. {$ENDIF}
  408.       FreeStatement;
  409.     end;
  410.     FPrepared := Value;
  411.   end;
  412. end;
  413.  
  414. procedure TQBEQuery.FreeStatement;
  415. begin
  416.   if StmtHandle <> nil then begin
  417.     DbiQFree(FStmtHandle);
  418.     FStmtHandle := nil;
  419.   end;
  420. end;
  421.  
  422. function TQBEQuery.ParamByName(const Value: string): TParam;
  423. begin
  424.   Result := FParams.ParamByName(Value);
  425. end;
  426.  
  427. procedure TQBEQuery.CreateParams(List: TParams; const Value: PChar);
  428. var
  429.   CurPos, StartPos: PChar;
  430.   CurChar: Char;
  431.   Literal: Boolean;
  432.   EmbeddedLiteral: Boolean;
  433.   Name: string;
  434.  
  435.   function StripLiterals(Buffer: PChar): string;
  436.   var
  437.     Len: Word;
  438.     TempBuf: PChar;
  439.  
  440.     procedure StripChar(Value: Char);
  441.     begin
  442.       if TempBuf^ = Value then
  443.         StrMove(TempBuf, TempBuf + 1, Len - 1);
  444.       if TempBuf[StrLen(TempBuf) - 1] = Value then
  445.         TempBuf[StrLen(TempBuf) - 1] := #0;
  446.     end;
  447.  
  448.   begin
  449.     Len := StrLen(Buffer) + 1;
  450.     TempBuf := AllocMem(Len);
  451.     Result := '';
  452.     try
  453.       StrCopy(TempBuf, Buffer);
  454.       StripChar('''');
  455.       StripChar('"');
  456.       Result := StrPas(TempBuf);
  457.     finally
  458.       FreeMem(TempBuf, Len);
  459.     end;
  460.   end;
  461.  
  462. begin
  463.   CurPos := Value;
  464.   Literal := False;
  465.   EmbeddedLiteral := False;
  466.   repeat
  467.     CurChar := CurPos^;
  468.     if (CurChar = FStartParam) and not Literal and
  469.       ((CurPos + 1)^ <> FStartParam) then
  470.     begin
  471.       StartPos := CurPos;
  472.       while (CurChar <> #0) and (Literal or not NameDelimiter(CurChar)) do
  473.       begin
  474.         Inc(CurPos);
  475.         CurChar := CurPos^;
  476.         if IsLiteral(CurChar) then begin
  477.           Literal := Literal xor True;
  478.           if CurPos = StartPos + 1 then EmbeddedLiteral := True;
  479.         end;
  480.       end;
  481.       CurPos^ := #0;
  482.       if EmbeddedLiteral then begin
  483.         Name := StripLiterals(StartPos + 1);
  484.         EmbeddedLiteral := False;
  485.       end
  486.       else Name := StrPas(StartPos + 1);
  487. {$IFDEF RX_D4}
  488.       if List.FindParam(Name) = nil then
  489. {$ENDIF}
  490.         List.CreateParam(ftUnknown, Name, ptUnknown);
  491.       CurPos^ := CurChar;
  492.       StartPos^ := '?';
  493.       Inc(StartPos);
  494.       StrMove(StartPos, CurPos, StrLen(CurPos) + 1);
  495.       CurPos := StartPos;
  496.     end
  497.     else if (CurChar = FStartParam) and not Literal
  498.       and ((CurPos + 1)^ = FStartParam) then
  499.       StrMove(CurPos, CurPos + 1, StrLen(CurPos) + 1)
  500.     else if IsLiteral(CurChar) then Literal := Literal xor True;
  501.     Inc(CurPos);
  502.   until CurChar = #0;
  503. end;
  504.  
  505. {$IFNDEF RX_D3}
  506. function TQBEQuery.IsEmpty: Boolean;
  507. begin
  508.   Result := IsDataSetEmpty(Self);
  509. end;
  510. {$ENDIF}
  511.  
  512. function TQBEQuery.CreateCursor(GenHandle: Boolean): HDBICur;
  513. begin
  514.   if QBE.Count > 0 then begin
  515.     SetPrepared(True);
  516.     Result := GetQueryCursor(GenHandle);
  517.   end
  518.   else Result := nil;
  519. end;
  520.  
  521. function TQBEQuery.CreateHandle: HDBICur;
  522. begin
  523.   Result := CreateCursor(True)
  524. end;
  525.  
  526. procedure TQBEQuery.ExecQBE;
  527. begin
  528.   CheckInActive;
  529.   SetDBFlag(dbfExecSQL, True);
  530.   try
  531.     CreateCursor(False);
  532.   finally
  533.     SetDBFlag(dbfExecSQL, False);
  534.   end;
  535. end;
  536.  
  537. function TQBEQuery.GetQueryCursor(GenHandle: Boolean): HDBICur;
  538. var
  539.   PCursor: phDBICur;
  540. begin
  541.   Result := nil;
  542.   if GenHandle then PCursor := @Result
  543.   else PCursor := nil;
  544.   Check(DbiQExec(StmtHandle, PCursor));
  545. end;
  546.  
  547. {$IFDEF RX_V110}
  548. function TQBEQuery.SetDBFlag(Flag: Integer; Value: Boolean): Boolean;
  549. {$ELSE}
  550. procedure TQBEQuery.SetDBFlag(Flag: Integer; Value: Boolean);
  551. {$ENDIF}
  552. var
  553.   NewConnection: Boolean;
  554. begin
  555.   if Value then begin
  556.     NewConnection := DBFlags = [];
  557. {$IFDEF RX_V110}
  558.     Result := inherited SetDBFlag(Flag, Value);
  559. {$ELSE}
  560.     inherited SetDBFlag(Flag, Value);
  561. {$ENDIF}
  562.     if not (csReading in ComponentState) and NewConnection then
  563.       FLocal := not Database.IsSQLBased;
  564.   end
  565.   else begin
  566.     if DBFlags - [Flag] = [] then SetPrepared(False);
  567. {$IFDEF RX_V110}
  568.     Result := inherited SetDBFlag(Flag, Value);
  569. {$ELSE}
  570.     inherited SetDBFlag(Flag, Value);
  571. {$ENDIF}
  572.   end;
  573. end;
  574.  
  575. procedure TQBEQuery.PrepareQBE(Value: PChar);
  576. begin
  577.   GetStatementHandle(Value);
  578. end;
  579.  
  580. procedure TQBEQuery.GetStatementHandle(QBEText: PChar);
  581. const
  582.   DataType: array[Boolean] of LongInt = (Ord(wantCanned), Ord(wantLive));
  583. begin
  584. {$IFDEF WIN32}
  585.   Check(DbiQAlloc(DBHandle, qrylangQBE, FStmtHandle));
  586.   try
  587.     Check(DBiSetProp(hDbiObj(StmtHandle), stmtLIVENESS,
  588.       DataType[RequestLive and not ForceUpdateCallback]));
  589.     Check(DBiSetProp(hDbiObj(StmtHandle), stmtAUXTBLS, Longint(FAuxiliaryTables)));
  590. {$IFDEF RX_D3}
  591.     if Local and RequestLive and Constrained then
  592.       Check(DBiSetProp(hDbiObj(StmtHandle), stmtCONSTRAINED, LongInt(True)));
  593. {$ENDIF}
  594.     if FBlankAsZero then
  595.       Check(DbiSetProp(hDbiObj(StmtHandle), stmtBLANKS, Longint(True)));
  596.     while not CheckOpen(DbiQPrepare(FStmtHandle, QBEText)) do {Retry};
  597.   except
  598.     DbiQFree(FStmtHandle);
  599.     FStmtHandle := nil;
  600.     raise;
  601.   end;
  602. {$ELSE}
  603.   if Local then begin
  604.     while not CheckOpen(DbiQPrepare(DBHandle, qrylangQBE, QBEText,
  605.       FStmtHandle)) do {Retry};
  606.     Check(DBiSetProp(hDbiObj(StmtHandle), stmtLIVENESS, DataType[RequestLive]));
  607.   end
  608.   else begin
  609.     if RequestLive then
  610.       Check(DbiQPrepareExt(DBHandle, qrylangQBE, QBEText, qprepFORUPDATE, FStmtHandle))
  611.     else Check(DbiQPrepare(DBHandle, qrylangQBE, QBEText, FStmtHandle));
  612.   end;
  613.   Check(DBiSetProp(hDbiObj(StmtHandle), stmtAUXTBLS, Longint(FAuxiliaryTables)));
  614.   if FBlankAsZero then
  615.     Check(DbiSetProp(hDbiObj(StmtHandle), stmtBLANKS, LongInt(True)));
  616. {$ENDIF}
  617. end;
  618.  
  619. function TQBEQuery.GetQBEText: PChar;
  620. var
  621.   BufLen: Word;
  622.   I: Integer;
  623.   StrEnd: PChar;
  624.   StrBuf: array[0..255] of Char;
  625. begin
  626.   BufLen := 1;
  627.   for I := 0 to QBE.Count - 1 do
  628.     Inc(BufLen, Length(QBE.Strings[I]) + 1);
  629.   Result := StrAlloc(BufLen);
  630.   try
  631.     StrEnd := Result;
  632.     for I := 0 to QBE.Count - 1 do begin
  633.       StrPCopy(StrBuf, QBE.Strings[I]);
  634.       StrEnd := StrECopy(StrEnd, StrBuf);
  635.       StrEnd := StrECopy(StrEnd, ' ');
  636.     end;
  637.   except
  638.     StrDispose(Result);
  639.     raise;
  640.   end;
  641. end;
  642.  
  643. {$IFDEF WIN32}
  644. function TQBEQuery.GetRowsAffected: Integer;
  645. var
  646.   Length: Word;
  647. begin
  648.   if Prepared then
  649.     if DbiGetProp(hDBIObj(StmtHandle), stmtROWCOUNT, @Result, SizeOf(Result),
  650.       Length) <> 0 then Result := -1
  651.     else
  652.   else Result := FRowsAffected;
  653. end;
  654. {$ENDIF}
  655.  
  656. {$IFDEF RX_D5}
  657.  
  658. { TQBEQuery.IProviderSupport }
  659.  
  660. function TQBEQuery.PSGetParams: TParams;
  661. begin
  662.   Result := Params;
  663. end;
  664.  
  665. procedure TQBEQuery.PSSetParams(AParams: TParams);
  666. begin
  667.   if AParams.Count <> 0 then
  668.     Params.Assign(AParams);
  669.   Close;
  670. end;
  671.  
  672. procedure TQBEQuery.PSExecute;
  673. begin
  674.   ExecQBE;
  675. end;
  676.  
  677. procedure TQBEQuery.PSSetCommandText(const CommandText: string);
  678. begin
  679.   if CommandText <> '' then
  680.     QBE.Text := CommandText;
  681. end;
  682.  
  683. {$ENDIF RX_D5}
  684.  
  685. end.